//
// Created by WangPeng on 2024/8/15.
//

#ifndef RTSP_H264_SERVER_RTP_PROTOCOL_H
#define RTSP_H264_SERVER_RTP_PROTOCOL_H

#include <cstdint>
#include <memory>

#define RTP_VERSION              2

#define RTP_PAYLOAD_TYPE_H264   96
#define RTP_PAYLOAD_TYPE_AAC    97

#define RTP_HEADER_SIZE         12
#define RTP_MAX_PKT_SIZE        1400

/*
 *    0                   1                   2                   3
 *    7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |V=2|P|X|  CC   |M|     PT      |       sequence number         |
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |                           timestamp                           |
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |           synchronization source (SSRC) identifier            |
 *   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 *   |            contributing source (CSRC) identifiers             |
 *   :                             ....                              :
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 */
//RTP协议头
struct RtpHeader
{
    /* byte 0 */
    uint8_t csrc_len : 4;//CSRC计数器，占4位，指示CSRC 标识符的个数。
    uint8_t extension : 1;//占1位，如果X=1，则在RTP报头后跟有一个扩展报头。
    uint8_t padding : 1;//填充标志，占1位，如果P=1，则在该报文的尾部填充一个或多个额外的八位组，它们不是有效载荷的一部分。
    uint8_t version : 2;//RTP协议的版本号，占2位，当前协议版本号为2。

    /* byte 1 */
    uint8_t payload_type : 7;//有效载荷类型，占7位，用于说明RTP报文中有效载荷的类型，如GSM音频、JPEM图像等。
    uint8_t marker : 1;//标记，占1位，不同的有效载荷有不同的含义，对于视频，标记一帧的结束；对于音频，标记会话的开始。

    /* bytes 2,3 */
    uint16_t seq;//占16位，用于标识发送者所发送的RTP报文的序列号，每发送一个报文，序列号增1。接收者通过序列号来检测报文丢失情况，重新排序报文，恢复数据。

    /* bytes 4-7 */
    uint32_t timestamp;//占32位，时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动，并进行同步控制。

    /* bytes 8-11 */
    uint32_t ssrc;//占32位，用于标识同步信源。该标识符是随机选择的，参加同一视频会议的两个同步信源不能有相同的SSRC。

    /*标准的RTP Header 还可能存在 0-15个特约信源(CSRC)标识符

    每个CSRC标识符占32位，可以有0～15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源

    */
};

//需要发送的RTP数据
struct RtpPacket
{
    struct RtpHeader hrtp; //rtp头部数据
    uint8_t payload[0]; //rtp数据载荷
};
class CUdpSocket;
class CRtpProtocol
{
public:
    CRtpProtocol();
    CRtpProtocol(uint8_t csrc_len, uint8_t extension,
                  uint8_t padding, uint8_t version,
                  uint8_t payload_type, uint8_t marker,
                  uint16_t seq, uint32_t timestamp,
                  uint32_t ssrc);

    ~CRtpProtocol();
    static int send_rtp_over_udp(CUdpSocket *udp_socket, struct RtpPacket *rtp_packet, uint32_t frame_size);
    struct RtpPacket* get_packet()
    {
        return packet_;
    }
private:
    struct RtpHeader rtp_header_{};
    struct RtpPacket* packet_{nullptr};
};

#endif //RTSP_H264_SERVER_RTP_PROTOCOL_H
